前言

陶瓷的许多接口都需要我们携带正确的 access_token 才能访问, 这个东西相当于现实中的身份证, 下面简称票据. 票据是通过我们用app_id和app_secret获取的. 而且每两个小时过期, 每日获取上限是2000次.

原理

我们在访问某些接口前, 先去获取票据, 携带上再访问接口. 但因为有每日2000次的限制, 所以我们获取后应该缓存到本地, 我是缓存到一个json文件中的. 又因为2个小时的过期时间, 所以我们应该在缓存票据的时候设置一个过期时间. 如果当前时间大于过期时间, 就代表票据失效了, 需要我们重新去获取票据.

其实还有另一种实现, 就是使用一个定时器, 每1.5小时自动获取票据并缓存, 不过这个要下载一个npm包.

实现

我使用了第一种实现.

//在调用某些接口前应该先调用这个方法, 
//flag参数是用来区分不同陶瓷的标志
//二次开发的目的在我看来是为了一个后台运营多个陶瓷
async getAccessToken(flag){
  //从缓存文件中获取存储了所有access_token的对象
  let allAccessTokenInfoObj = FileUtil.getJsonObjFromFile(weixinConfig.common.accessTokenFilePath)
  //判断access_token的合法性
  if(!this._isValidAccessToken(allAccessTokenInfoObj,flag)){
    //如果不合法就去微信后台重新获取access_token,并缓存
    allAccessTokenInfoObj = await this._updateAccessToken(allAccessTokenInfoObj,flag)
  }
  //返回我们需要的access_token
  return allAccessTokenInfoObj[flag].accessToken    
}

/**
   * @Date: 2020-10-22 15:21:00
   * @author: qiud
   * @description: 验证票据是否有效
   * 1. 票据不存在
   * 2. 票据过期
   * @param {object} allAccessTokenInfoObj 所有票据的对象
   * @param {string} flag 陶瓷标识, 用来判断获取哪个公众的票据
   * @return {boolean} 是否有效
   */  
  _isValidAccessToken(allAccessTokenInfoObj,flag){
    //文件中没有accessToken信息,或者不完整
    if(!allAccessTokenInfoObj[flag] || Object.keys(allAccessTokenInfoObj[flag]).length < 2){
      return false
    }
    //有accessToken信息, 但已经过期
    const now = new Date().getTime()
    if(allAccessTokenInfoObj[flag].expireTime<=now){
      return false
    }
    return true
  }

  /**
   * @Date: 2020-10-22 15:20:02
   * @author: qiud
   * @description: 更新票据
   * @param {object} allAccessTokenInfoObj 存储所有票据的对象
   * @param {string} flag 陶瓷标识, 用来判断获取哪个公众的票据
   * @return {Promise<object>} 所有票据对象, 包含过期时间
   */  
  async _updateAccessToken(allAccessTokenInfoObj,flag){
    //根据flag去数据库找到对应appId和secret
    const platformInfo = await WeiXinPlatformModel.findOne({
      where:{
        flag,
      }
    })
    if(!platformInfo){
      throw new NotFound(`标识符 ${flag} 没有对应的陶瓷!`) 
    }
    //组装请求票据的url
    const url = StrUtil.replace(weixinConfig.api.getAccessTokenGet,[platformInfo.appId,platformInfo.appSecret])
    //请求票据
    const res = await axios({
      url,
      method:'GET',
    })
    if(res.data.errcode){
      throw new GetAccessTokenException(res.data.errmsg)
    }
    //设置过期时间
    const expireTime = TimeUtil.createExpireTimestamp(weixinConfig.common.expireTime)
    //把新票据和过期时间整合到所有票据对象上面
    allAccessTokenInfoObj[flag] = {
      accessToken:res.data.access_token,
      expireTime,
    }
    //保存到缓存文件中
    FileUtil.saveJsonObjToFile(weixinConfig.common.accessTokenFilePath,allAccessTokenInfoObj)
    //返回所有票据对象
    return allAccessTokenInfoObj
  }

总结

整个实现是非常清晰的, 我们来复盘下.

  1. 去缓存文件找到对应的票据,
  2. 验证这个票据的合法性. 如果合法则直接获取该票据. 不合法则先去微信后台请求票据, 再缓存起来, 最后返回票据对象.
  3. 拿到我们需要的票据.
THE END
推荐文章
  • wsl设置root密码

  • 让win10每天定时自动关机

  • 字符编码ASCII, GB2312, Unicode和UTF-8之间的区别

  • 黄帝内经-第十八篇-平人气象论篇(3)

  • docker-compose问题集合

  • 微信把地区设置为中国大陆

  • taro&小程序 button按钮去除border边框

  • 保存vscode配置的同步插件设置

评论 共0条
开启精彩搜索

热门搜索

暂无

历史搜索

用户名/邮箱/手机号
密码
用户名
密码
重复密码
邮箱/手机号
验证码
发送验证码
59秒后可重发
注册
找回密码
邮箱/手机号
验证码
发送验证码
59秒后可重发
新密码
重复密码
请选择支付方式
余额支付

购买将消耗【10

微信支付
微信扫码支付 0 元
[ 04分50秒 ]
请使用微信扫一扫
扫描二维码支付
支付宝支付
支付宝扫码支付 0 元
[ 04分50秒 ]
请使用支付宝扫一扫
扫描二维码支付
已完成支付
未完成支付

请输入验证码

点击验证码可以刷新

你确认吗?

确认

2024年10月1日

0字

0字

2024年10月

0字

新增

0字

新增

0字

0字

新增

0字

0字

新增

0字

0字

新增

0字

0字

新增

0字

0字

新增

0字

0字

新增

0字

0字

0字

新增

0字

0字

0字

0字

新增

0字

0字